home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 10
/
amigaformatcd10.iso
/
-screenplay-
/
shareware
/
mris 1.1
/
.mris1_1src.lha
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-16
|
84KB
|
3,550 lines
#ifndef DEVICES_GAMEPORT_H
#include <devices/gameport.h>
#endif
#ifndef PREFS_PREFHDR_H
#include <prefs/prefhdr.h>
#endif
#ifndef DOS_EXALL_H
#include <dos/exall.h>
#endif
#ifndef WORKBENCH_STARTUP_H
#include <workbench/startup.h>
#endif
#ifndef INTUITION_IMAGECLASS_H
#include <intuition/imageclass.h>
#endif
#ifndef GRAPHICS_VIDEOCONTROL_H
#include <graphics/videocontrol.h>
#endif
#include <proto/locale.h>
#include <proto/layers.h>
#include <proto/commodities.h>
#include <proto/gadtools.h>
#include <proto/diskfont.h>
#include <proto/icon.h>
#include <proto/wb.h>
#include <proto/asl.h>
#include <proto/utility.h>
#include "Version.h"
#define CATCOMP_BLOCK
#include "xmris.h"
#include "defmris.h"
#include "ConfigKeys.h"
#include "ChangeUser.h"
#include "Manual.h"
#include "BOOPSILib.h"
#include "ConfigFont.h"
#include "ConfigScreen.h"
#include "Errors.h"
#include "StaticSavedsAsmA1A2.h"
#include "Catalog.h"
#define JOYSTICK_TRIES 200
/************************************************************************/
const char VersionString[]=
"$VER: " PROGRAM_NAME " " PROGRAM_VERSION " (" PROGRAM_DATE ")based on Xmris " XMRISVERSION " (" DATE ")";
const ULONG StackSize=45000;
/************************************************************************/
extern struct DiskObject mrisIcon;
/************************************************************************/
struct GameSupportBase *GameSupportBase;
struct DosLibrary *DOSBase;
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct Library *UtilityBase;
struct Library *LocaleBase;
struct Library *LayersBase;
struct Library *CxBase;
struct Library *GadToolsBase;
struct Library *KeymapBase;
struct Library *IconBase;
struct Library *WorkbenchBase;
struct Locale *Locale;
struct Catalog *Catalog;
struct TimeFormats Formats;
#if defined(__SASC)
UWORD __chip DitherPattern[2]={0x5555,0xaaaa};
#else
UWORD *DitherPattern;
#endif
struct MiscState MiscState;
struct MsgPort WindowPort=
{
{NULL,NULL,NT_MSGPORT,0,NULL},
PA_SIGNAL,
0,
NULL,
{(struct Node *)&WindowPort.mp_MsgList.lh_Tail,NULL,(struct Node *)&WindowPort.mp_MsgList.lh_Head,NT_MESSAGE}
};
struct MsgPort MiscPort=
{
{NULL,NULL,NT_MSGPORT,0,NULL},
PA_SIGNAL,
0,
NULL,
{(struct Node *)&MiscPort.mp_MsgList.lh_Tail,NULL,(struct Node *)&MiscPort.mp_MsgList.lh_Head,NT_MESSAGE}
};
struct TextAttr TextAttr;
char *ScreenDescription;
/************************************************************************/
static char *WindowTitle;
static ULONG AllocateJoystickCounter;
static struct Window *About;
static struct Window *CompileInfo;
extern const char CompileDate[];
extern const char CompileTime[];
static BPTR GardenDir;
static struct MsgPort WBPort=
{
{NULL,NULL,NT_MSGPORT,0,NULL},
PA_SIGNAL,
SIGBREAKB_CTRL_F,
NULL,
{(struct Node *)&WBPort.mp_MsgList.lh_Tail,NULL,(struct Node *)&WBPort.mp_MsgList.lh_Head,NT_MESSAGE}
};
static CxObj *Broker;
static struct NewBroker NewBroker=
{
NB_VERSION,
NULL,
NULL,
NULL,
NBU_UNIQUE,
COF_SHOW_HIDE,
0,
&MiscPort
};
static struct AsyncAslMessage ConfigMessage;
static struct Gadget IconifyGadget=
{
NULL,
0,0,0,0,
GFLG_GADGHIMAGE | GFLG_GADGIMAGE | GFLG_RELRIGHT,
GACT_RELVERIFY | GACT_TOPBORDER,
GTYP_BOOLGADGET,
NULL,
NULL,
NULL,
0,
NULL,
0,
NULL
};
/************************************************************************/
static const char * const MrisToolTypes[]=
{
"UP", /* 0 */
"DOWN", /* 1 */
"LEFT", /* 2 */
"RIGHT", /* 3 */
"THROW", /* 4 */
"PAUSE", /* 5 */
"QUIT", /* 6 */
"ICONIZE", /* 7 */
"RANDOM", /* 8 */
"DYNAMIC", /* 9 */
"USER", /* 10 */
"PUBSCREEN", /* 11 */
"SCREEN", /* 12 */
"JOYSTICK", /* 13 */
"FONT", /* 14 */
"MSIT" /* 15 */
};
/************************************************************************/
static int ProcessMisc(void);
/************************************************************************/
/* */
/* Compare two scores */
/* */
/************************************************************************/
STATIC_SAVEDS_ASM_A1A2(ULONG,ScoreCompareCode,void *,Score2,void *,Score1)
{
LONG Diff;
Diff=((HIGH_SCORE *)Score1)->score-((HIGH_SCORE *)Score2)->score;
if (Diff==0)
{
Diff=((HIGH_SCORE *)Score1)->screen-((HIGH_SCORE *)Score2)->screen;
if (Diff==0)
{
Diff=((HIGH_SCORE *)Score1)->elapsed-((HIGH_SCORE *)Score2)->elapsed;
if (Diff==0)
{
Diff=((HIGH_SCORE *)Score1)->Score.TimeStamp-((HIGH_SCORE *)Score2)->Score.TimeStamp;
}
}
}
return (ULONG)Diff;
}
/*--------------------*/
static const struct Hook ScoreCompareHook=
{
{NULL,NULL},ScoreCompareCode,NULL,NULL
};
/************************************************************************/
const struct ScoreDef ScoreDef=
{
{
&ScoreCompareHook,
PROGRAM_NAME,
{ HIGH_SCORES, HIGH_SCORES, HIGH_SCORES },
ARRAYSIZE(ScoreDef.Chunks)
},
{
{MAKE_ID('S','C','O','R'),GS_SCOREDEFF_INTEGER,sizeof(ULONG)},
{MAKE_ID('L','E','V','L'),GS_SCOREDEFF_INTEGER,sizeof(ULONG)},
{MAKE_ID('E','L','A','P'),GS_SCOREDEFF_INTEGER,sizeof(ULONG)}
}
};
/************************************************************************/
#define NM(Type,Name,Flags) {NM_##Type,(STRPTR)MSG_##Name##_MENU,NULL,Flags,0,(APTR)MSG_##Name##_MENU}
static struct NewMenu NewMenu[]=
{
{NM_TITLE,(STRPTR)MSG_GAME_MENU,NULL,0,0,NULL},
NM(ITEM,GAME_USER,0),
NM(ITEM,GAME_ERRORS,0),
{NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
NM(ITEM,GAME_ABOUT,0),
{NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
NM(ITEM,GAME_QUIT,0),
{NM_TITLE,(STRPTR)MSG_GARDENS_MENU,NULL,0,0,(APTR)MSG_GARDENS_MENU},
{NM_TITLE,(STRPTR)MSG_DEMO_MENU,NULL,0,0,(APTR)MSG_DEMO_MENU},
NM(ITEM,DEMO_SCORES,NM_ITEMDISABLED),
NM(ITEM,DEMO_BOARD,NM_ITEMDISABLED),
NM(ITEM,DEMO_KEYS,0),
NM(ITEM,DEMO_NAME,0),
NM(ITEM,DEMO_SPRITES,0),
{NM_TITLE,(STRPTR)MSG_CONFIG_MENU,NULL,0,0,NULL},
NM(ITEM,CONFIG_RANDOM,CHECKIT | MENUTOGGLE),
{NM_ITEM,(STRPTR)MSG_CONFIG_CONTROL_MENU,NULL,0,0,NULL},
NM(SUB,CONFIG_CONTROL_JOYSTICK,CHECKIT | MENUTOGGLE | CHECKED),
NM(SUB,CONFIG_CONTROL_KEYS,0),
{NM_ITEM,(STRPTR)MSG_CONFIG_DISPLAY_MENU,NULL,0,0,NULL},
NM(SUB,CONFIG_DISPLAY_MSIT,CHECKIT | MENUTOGGLE),
NM(SUB,CONFIG_DISPLAY_DYNAMIC,CHECKIT | MENUTOGGLE | CHECKED),
NM(SUB,CONFIG_DISPLAY_SCREEN,0),
NM(SUB,CONFIG_DISPLAY_FONT,0),
{NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
NM(ITEM,CONFIG_SAVE,0),
NM(ITEM,CONFIG_SAVEDEFAULT,0),
{NM_END}
};
struct StringNode
{
struct StringNode *Next;
};
static struct StringNode *GardenStrings;
/************************************************************************/
/* */
/* */
/************************************************************************/
void FreeBOOPSIClasses(void)
{
if (FreeClass(BOOPSILibC_Root))
{
BOOPSILibC_Root=NULL;
}
if (FreeClass(BOOPSILibC_Group))
{
BOOPSILibC_Group=NULL;
}
if (FreeClass(BOOPSILibC_String))
{
BOOPSILibC_String=NULL;
}
if (FreeClass(BOOPSILibC_Button))
{
BOOPSILibC_Button=NULL;
}
if (FreeClass(BOOPSILibC_Label))
{
BOOPSILibC_Label=NULL;
}
if (FreeClass(BOOPSILibC_Frame))
{
BOOPSILibC_Frame=NULL;
}
}
/************************************************************************/
int CreateBOOPSIClasses(void)
{
if (BOOPSILibC_Group!=NULL || CreateBOOPSILibC_Group()!=NULL)
{
if (BOOPSILibC_String!=NULL || CreateBOOPSILibC_String()!=NULL)
{
if (BOOPSILibC_Button!=NULL || CreateBOOPSILibC_Button()!=NULL)
{
if (BOOPSILibC_Label!=NULL || CreateBOOPSILibC_Label()!=NULL)
{
if (BOOPSILibC_Frame!=NULL || CreateBOOPSILibC_Frame()!=NULL)
{
if (BOOPSILibC_Root!=NULL || CreateBOOPSILibC_Root()!=NULL)
{
return TRUE;
}
}
}
}
}
}
FreeBOOPSIClasses();
return FALSE;
}
/************************************************************************/
/* */
/* Delete a Pixmap */
/* */
/************************************************************************/
static void DeletePixmap(Pixmap *Data)
{
if (Data->Layer!=NULL)
{
while (!DeleteLayer(0,Data->Layer))
{
Delay(TICKS_PER_SECOND); /* anyone with a better idea? */
}
Data->Layer=NULL;
}
if (Data->LayerInfo!=NULL)
{
DisposeLayerInfo(Data->LayerInfo);
Data->LayerInfo=NULL;
}
WaitBlit();
FreeBitMap(Data->BitMap);
Data->BitMap=NULL;
}
/************************************************************************/
/* */
/* Delete our offscreen bitmaps */
/* */
/************************************************************************/
static void FreeBitmaps(void)
{
int i;
DeletePixmap(&display.copy);
DeletePixmap(&display.back);
for (i=0; i<BOARD_SCORES; i++)
{
DeletePixmap(&update.score.list[i].image);
DeletePixmap(&update.score.list[i].mask);
}
}
/************************************************************************/
/* */
/* */
/************************************************************************/
static void FreeJoystick(void)
{
if (MiscState.Joystick)
{
MiscState.Joystick=FALSE;
AbortIO(&GameSupportBase->Joystick.Request);
WaitIO(&GameSupportBase->Joystick.Request);
GS_FreeJoystick();
}
AllocateJoystickCounter=0;
}
/************************************************************************/
/* */
/* Free dynamic colors */
/* */
/************************************************************************/
static void ReleaseDynamic(void)
{
if (display.dynamic)
{
struct ColorMap *ColorMap;
ColorMap=display.Screen->Screen->ViewPort.ColorMap;
ReleasePen(ColorMap,display.DynamicColor2);
ReleasePen(ColorMap,display.DynamicColor1);
display.dynamic=FALSE;
}
}
/************************************************************************/
/* */
/* Free the sprites */
/* */
/************************************************************************/
static void FreeSprites(void)
{
if (Sprites!=NULL)
{
if (display.window!=NULL)
{
SetABPenDrMd(display.window->RPort,0,0,JAM1);
RectFill(display.window->RPort,display.OriginX,display.OriginY,
display.OriginX+WINDOW_WIDTH-1,display.OriginY+WINDOW_HEIGHT-1);
}
ReleaseDynamic();
GS_FreeSprites(Sprites,display.Screen->Screen);
Sprites=NULL;
FreeSysRequest(About);
About=NULL;
}
}
/************************************************************************/
/* */
/* Process a "key". */
/* */
/************************************************************************/
static INLINE void KeyDown(int Key)
{
global.pressed|=1<<Key;
if (Key==KEY_PAUSE)
{
timer_set((unsigned long)0, TIMING_PAUSE);
global.pause = 1;
}
}
/************************************************************************/
static INLINE void KeyUp(int Key)
{
global.pressed&=~(1<<Key);
}
/************************************************************************/
/* */
/* */
/************************************************************************/
static void InactiveWindow(void)
{
int Key;
FreeJoystick();
if (MiscState.GameMode)
{
KeyDown(KEY_PAUSE);
}
for (Key=0; Key<KEYS; Key++)
{
KeyUp(Key);
}
}
/************************************************************************/
/* */
/* Free all GUI related resources (except for the menu) */
/* */
/************************************************************************/
static void CloseGUI(void)
{
if (!ErrorFlag)
{
CloseErrorWindow();
}
if (display.Screen!=NULL)
{
if (display.VisualInfo!=NULL)
{
if (display.window!=NULL)
{
InactiveWindow();
CloseConfigKeysWindow();
CloseChangeUserWindow();
CloseManual();
FreeSysRequest(CompileInfo);
CompileInfo=NULL;
global.pressed=0;
FreeSprites();
ClearMenuStrip(display.window);
((struct Process *)WindowPort.mp_SigTask)->pr_WindowPtr=display.window->UserData;
CloseWindowSafely(display.window);
display.window=NULL;
FreeBitmaps();
if (IconifyImageClass!=NULL)
{
DisposeObject(IconifyGadget.GadgetRender);
IconifyGadget.GadgetRender=NULL;
FreeClass(IconifyImageClass);
IconifyImageClass=NULL;
}
if (MiscState.HappyBlanker)
{
MiscState.HappyBlanker=FALSE;
GS_NoHappyBlanker();
}
}
if (data.font!=NULL)
{
CloseFont(data.font);
data.font=NULL;
}
FreeVisualInfo(display.VisualInfo);
display.VisualInfo=NULL;
}
FreeScreenDrawInfo(display.Screen->Screen,display.DrawInfo);
if (FreeScreen(display.Screen,FALSE))
{
display.Screen=NULL;
}
}
ErrorFlag=FALSE;
}
/************************************************************************/
/* */
/* Change key description */
/* In case of failure, the key is not changed. */
/* If Description==NULL, the default binding is used */
/* */
/************************************************************************/
int ChangeKey(int Key, char *Description)
{
if (Description==NULL)
{
if (Key==KEYS)
{
Description="help";
}
else if (Key==KEYS+1)
{
Description="lshift rshift help";
}
else
{
Description=GetString(MSG_KEY_UP+Key);
}
ParseIX(data.keysyms[Key].Description=Description,&data.keysyms[Key].InputXpression);
}
else
{
struct InputXpression InputXpression;
char *String;
if (ParseIX(Description,&InputXpression)!=0 || InputXpression.ix_Class!=IECLASS_RAWKEY)
{
DisplayError(MSG_INVALIDKEY_ERROR,Description,GetString(MSG_DEMO_UP+Key));
return FALSE;
}
if ((String=GS_MemoryAlloc(strlen(Description)+1))==NULL)
{
DisplayError(0,ERROR_NO_FREE_STORE);
return FALSE;
}
if (data.keysyms[Key].Description!=GetString(MSG_KEY_UP+Key))
{
GS_MemoryFree(data.keysyms[Key].Description);
}
strcpy((data.keysyms[Key].Description=String),Description);
data.keysyms[Key].InputXpression=InputXpression;
}
return TRUE;
}
/************************************************************************/
/* */
/* Free key descriptions */
/* */
/************************************************************************/
static INLINE void FreeKeys(void)
{
int Key;
for (Key=0; Key<KEYS; Key++)
{
ChangeKey(Key,NULL);
}
}
/************************************************************************/
/* */
/* */
/************************************************************************/
static INLINE void FreeGardens(void)
{
struct Menu *Menu;
Menu=FindMenu(MSG_GARDENS_MENU);
while (Menu->FirstItem!=NULL)
{
struct MenuItem *Item;
Item=Menu->FirstItem;
Menu->FirstItem=Item->NextItem;
Item->NextItem=NULL;
FreeMenus((struct Menu *)Item);
}
}
/************************************************************************/
/* */
/* */
/************************************************************************/
static void CloseAll(int RC, LONG Error)
{
if (GadToolsBase!=NULL)
{
if (GameSupportBase!=NULL)
{
if (CxBase!=NULL)
{
CloseErrorWindow();
FreeErrors();
DeleteCxObj(Broker);
#if !defined(__SASC)
if (DitherPattern!=NULL)
{
#endif
CloseGUI();
if (board.list!=NULL)
{
FreeFile((LONG *)(((char *)board.list)-12)-1);
}
FreeKeys();
#if !defined(__SASC)
FreeMem(DitherPattern,2*sizeof(UWORD));
}
#endif
while (FontMessage.Message.mn_Node.ln_Type!=NT_UNKNOWN ||
ConfigMessage.Message.mn_Node.ln_Type!=NT_UNKNOWN ||
ScreenMessage.Message.mn_Node.ln_Type!=NT_UNKNOWN)
{
WaitPort(&MiscPort);
ProcessMisc();
}
while (ProcessMisc())
;
GS_MemoryFree(WindowTitle);
GS_ReleaseScoreHandle(scoring.ScoreHandle);
if (display.Menustrip!=NULL)
{
FreeGardens();
FreeMenus(display.Menustrip);
}
while (GardenStrings!=NULL)
{
struct GardenString *Next;
Next=GardenStrings->Next;
GS_MemoryFree(GardenStrings);
GardenStrings=Next;
}
if (Locale!=NULL)
{
CloseCatalog(Catalog);
CloseLocale(Locale);
}
FreeVec(TextAttr.ta_Name);
CloseLibrary(CxBase);
if (display.Screen!=NULL)
{
FreeScreen(display.Screen,TRUE);
}
}
if (GardenDir!=MKBADDR(NULL))
{
UnLock(GardenDir);
}
GS_MemoryFree(ScreenDescription);
GS_MemoryFree(NewBroker.nb_Name);
CloseLibrary(&GameSupportBase->Library);
}
CloseLibrary(GadToolsBase);
CloseLibrary(IconBase);
}
FreeSignal(MiscPort.mp_SigBit);
MyExit(RC,Error);
}
/************************************************************************/
/* */
/* Install a clipping rectangle into a Pixmap */
/* */
/************************************************************************/
struct Region *InstallBounds(Pixmap *Data, struct Rectangle Rectangle)
{
struct Region *Region;
assert(Data->Layer!=NULL);
if ((Region=NewRegion())!=NULL)
{
if (OrRectRegion(Region,&Rectangle))
{
struct Region *OldRegion;
OldRegion=InstallClipRegion(Data->Layer,Region);
assert(OldRegion==NULL);
return Region;
}
DisposeRegion(Region);
}
return NULL;
}
/************************************************************************/
/* */
/* Remove the current clipping rectangle from the Pixmap */
/* */
/************************************************************************/
void RemoveBounds(Pixmap *Data)
{
struct Region *Region;
assert(Data->Layer!=NULL);
Region=InstallClipRegion(Data->Layer,NULL);
assert(Region!=NULL);
DisposeRegion(Region);
}
/************************************************************************/
/* */
/* Get a localized string */
/* */
/************************************************************************/
const char *GetString(LONG StringID)
{
const char *String;
String=LocaleBase!=NULL ? (char *)GetCatalogStr(Catalog,StringID,NULL) : NULL;
if (String==NULL)
{
const LONG *l;
const UWORD *w;
l=(const LONG *)CatCompBlock;
while (*l != StringID)
{
w=(const UWORD *)((ULONG)l + 4);
l=(const LONG *)((ULONG)l + (ULONG)*w +6);
}
String=(char *)((ULONG)l + 6);
}
return String;
}
/************************************************************************/
/* */
/* Obtain dynamic colors, if required */
/* */
/************************************************************************/
static void ObtainDynamic(void)
{
display.dynamic=FALSE;
if (GfxBase->LibNode.lib_Version>=39)
{
if (!data.mono)
{
struct ColorMap *ColorMap;
if ((ColorMap=display.Screen->Screen->ViewPort.ColorMap)!=NULL)
{
if ((display.DynamicColor1=ObtainPen(ColorMap,-1,0,0,0,PENF_EXCLUSIVE | PENF_NO_SETCOLOR))!=~0)
{
if ((display.DynamicColor2=ObtainPen(ColorMap,-1,0,0,0,PENF_EXCLUSIVE | PENF_NO_SETCOLOR))!=~0)
{
display.dynamic=TRUE;
}
else
{
ReleasePen(ColorMap,display.DynamicColor1);
}
}
}
}
}
}
/************************************************************************/
/* */
/* */
/************************************************************************/
void Sleep(void)
{
MiscState.Sleep=TRUE;
GS_WindowSleep(display.window);
GS_WindowSleep(ConfigKeysWindow);
GS_WindowSleep(ChangeUserWindow);
GS_WindowSleep(ErrorWindow);
}
/************************************************************************/
void Wakeup(void)
{
MiscState.Sleep=FALSE;
GS_WindowWakeup(ChangeUserWindow);
GS_WindowWakeup(ConfigKeysWindow);
GS_WindowWakeup(display.window);
GS_WindowWakeup(ErrorWindow);
}
/************************************************************************/
/* */
/* Load the sprites */
/* */
/************************************************************************/
static int LoadSprites(void)
{
struct MenuItem *Item;
const char *Name;
ULONG Gender;
Sleep();
Item=(struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU);
Gender=!!(Item->Flags & CHECKED);
Name=Gender ? "msit" : "mris";
if ((Sprites=GS_LoadSprites(Name,display.Screen->Screen))==NULL)
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_SPRITES_ERROR,Name,ErrorString(String,IoErr()));
Gender=!Gender;
Name=Gender ? "msit" : "mris";
if ((Sprites=GS_LoadSprites(Name,display.Screen->Screen))==NULL)
{
DisplayError(MSG_SPRITES_ERROR,Name,ErrorString(String,IoErr()));
}
}
if (Sprites!=NULL)
{
WORD x;
struct RastPort RastPort;
data.gender=Gender;
ClearMenuStrip(display.window);
if (Gender)
{
Item->Flags|=CHECKED;
memcpy(ball_hold,she_hold,sizeof(ball_hold));
lettering[0] = letter_msit;
}
else
{
Item->Flags&=~CHECKED;
memcpy(ball_hold,he_hold,sizeof(ball_hold));
lettering[0] = letter_mris;
}
ResetMenuStrip(display.window,display.Menustrip);
sprites=(SPRITE *)Sprites->Sprites;
InitRastPort(&RastPort);
RastPort.BitMap=sprites[SPRITE_SPECIAL].image;
for (x=0; x<=7; x++)
{
backgrounds[x>>1][x&1]=ReadPixel(&RastPort,x,0);
}
display.black=ReadPixel(&RastPort,8,0);
display.white=ReadPixel(&RastPort,9,0);
display.border=ReadPixel(&RastPort,10,0);
data.mono=(Sprites->Colors.ColorCount==2);
if (((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags&CHECKED)
{
ObtainDynamic();
}
/* create display.xorBitmap */
{
ULONG xor;
int Plane;
xor=display.black^display.white;
assert((xor&~0xff)==0);
for (Plane=0; Plane<ARRAYSIZE(display.xorBitmap.Planes); Plane++)
{
display.xorBitmap.Planes[Plane]=(xor&(1<<Plane)) ? (PLANEPTR)~0 : (PLANEPTR)0;
}
display.xorBitmap.Depth=ARRAYSIZE(display.xorBitmap.Planes);
display.xorBitmap.BytesPerRow=((WINDOW_WIDTH+15)/16)*2;
display.xorBitmap.Rows=WINDOW_HEIGHT;
}
/*{{{ set foreground & background types*/
{
ULONG Set;
ULONG Clear;
ULONG i;
Set = 0;
Clear = (1<<display.DrawInfo->dri_Depth)-1;
/*{{{ set on and off*/
for(i=0; i<Sprites->Colors.ColorCount; i++)
{
Set|=Sprites->Colors.Colors[i].Pen;
Clear&=Sprites->Colors.Colors[i].Pen;
}
/*}}}*/
display.background = display.white == Clear ? COLOUR_ZERO :
display.white == Set ? COLOUR_ONE : COLOUR_WEIRD;
display.foreground = display.black == Clear ? COLOUR_ZERO :
display.black == Set ? COLOUR_ONE : COLOUR_WEIRD;
}
/*{{{ create fills*/
if (data.mono)
{
int i;
SetDrMd(&RastPort,JAM1);
SetAfPt(&RastPort,DitherPattern,1);
for (i=0; i<FILLS; i++)
{
SPRITE *sptr;
sptr=&sprites[SPRITE_FILLS+i];
RastPort.BitMap=sptr->image;
RectFill(&RastPort,0,0,sptr->size.x-1,sptr->size.y-1);
}
}
/*{{{ digits special*/
{
SPRITE *dptr;
dptr = &sprites[SPRITE_DIGITS];
XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
0, 0, dptr->size.x, dptr->size.y);
XCopyArea(display.display, dptr->mask, display.back, GCN(GC_MASK),
0, 0, dptr->size.x, dptr->size.y, 0, 0);
XCopyArea(display.display, display.back, dptr->image, GCN(GC_OR),
0, 0, dptr->size.x, dptr->size.y, 0, 0);
}
}
Wakeup();
BeginRefresh(display.window);
EndRefresh(display.window,TRUE);
return Sprites!=NULL;
}
/************************************************************************/
/* */
/* Allocate a fullsize offscreen bitmap */
/* */
/************************************************************************/
static int CreateOffscreen(Pixmap *Data)
{
if ((Data->LayerInfo=NewLayerInfo())!=NULL)
{
Data->BitMap=AllocBitMap(WINDOW_WIDTH,WINDOW_HEIGHT,display.DrawInfo->dri_Depth,
BMF_CLEAR | BMF_INTERLEAVED,display.Screen->Screen->RastPort.BitMap);
if (Data->BitMap!=NULL)
{
Data->Layer=CreateBehindLayer(Data->LayerInfo,Data->BitMap,0,0,WINDOW_WIDTH-1,WINDOW_HEIGHT-1,LAYERSIMPLE,NULL);
if (Data->Layer!=NULL)
{
SetFont(Data->Layer->rp,data.font);
return TRUE;
}
}
}
return FALSE;
}
/************************************************************************/
/* */
/* Allocate our various offscreen bitmaps */
/* */
/************************************************************************/
static INLINE int AllocateBitmaps(void)
{
if (CreateOffscreen(&display.copy))
{
if (CreateOffscreen(&display.back))
{
int i;
for (i=0; i<BOARD_SCORES; i++)
{
update.score.list[i].image.BitMap=AllocBitMap(DIGIT_WIDTH*4,DIGIT_HEIGHT,display.DrawInfo->dri_Depth,
BMF_INTERLEAVED,display.Screen->Screen->RastPort.BitMap);
if (update.score.list[i].image.BitMap==NULL)
{
break;
}
update.score.list[i].mask.BitMap=AllocBitMap(DIGIT_WIDTH*4,DIGIT_HEIGHT,display.DrawInfo->dri_Depth,
BMF_INTERLEAVED,display.Screen->Screen->RastPort.BitMap);
if (update.score.list[i].mask.BitMap==NULL)
{
break;
}
}
if (i==BOARD_SCORES)
{
return TRUE;
}
}
}
FreeBitmaps();
return FALSE;
}
/************************************************************************/
/* */
/* Process an JoystickEvent */
/* */
/************************************************************************/
static INLINE void HandleJoystick(void)
{
switch (GameSupportBase->Joystick.Event.ie_Code)
{
case IECODE_LBUTTON:
KeyDown(KEY_THROW);
break;
case IECODE_RBUTTON:
KeyDown(KEY_PAUSE);
break;
case IECODE_LBUTTON | IECODE_UP_PREFIX:
KeyUp(KEY_THROW);
break;
case IECODE_RBUTTON | IECODE_UP_PREFIX:
KeyUp(KEY_PAUSE);
break;
case IECODE_NOBUTTON:
switch (GameSupportBase->Joystick.Event.ie_X)
{
case 1:
KeyUp(KEY_LEFT);
KeyDown(KEY_RIGHT);
break;
case -1:
KeyUp(KEY_RIGHT);
KeyDown(KEY_LEFT);
break;
case 0:
KeyUp(KEY_RIGHT);
KeyUp(KEY_LEFT);
break;
}
switch (GameSupportBase->Joystick.Event.ie_Y)
{
case 1:
KeyUp(KEY_UP);
KeyDown(KEY_DOWN);
break;
case -1:
KeyUp(KEY_DOWN);
KeyDown(KEY_UP);
break;
case 0:
KeyUp(KEY_UP);
KeyUp(KEY_DOWN);
break;
}
break;
}
GS_SendJoystick();
}
/************************************************************************/
/* */
/* Create a message window */
/* */
/************************************************************************/
static struct Window *CreateMessage(const char *Title, const char *Template, ...)
{
struct EasyStruct EasyStruct;
struct Window *Window;
EasyStruct.es_StructSize=5*4;
EasyStruct.es_Flags=0;
EasyStruct.es_Title=(char *)Title;
EasyStruct.es_TextFormat=(char *)Template;
EasyStruct.es_GadgetFormat=GetString(MSG_MESSAGE_WINDOW_CLOSE);
Window=BuildEasyRequestArgs(display.window,&EasyStruct,0,&Template+1);
if (Window==(struct Window *)1)
{
Window=NULL;
}
return Window;
}
/************************************************************************/
/* */
/* Process an IDCMP_RAWKEY event */
/* */
/************************************************************************/
static INLINE void HandleKey(const struct IntuiMessage *Message)
{
if (!(Message->Qualifier & IEQUALIFIER_REPEAT))
{
struct InputEvent InputEvent;
int Key;
InputEvent.ie_NextEvent=NULL;
InputEvent.ie_Class=IECLASS_RAWKEY;
InputEvent.ie_SubClass=0;
InputEvent.ie_Code=Message->Code&~IECODE_UP_PREFIX;
InputEvent.ie_Qualifier=Message->Qualifier;
InputEvent.ie_position.ie_addr=*(APTR *)Message->IAddress;
InputEvent.ie_TimeStamp.tv_secs=Message->Seconds;
InputEvent.ie_TimeStamp.tv_micro=Message->Micros;
for (Key=0; Key<ARRAYSIZE(data.keysyms); Key++)
{
if (MatchIX(&InputEvent,&data.keysyms[Key].InputXpression))
{
if (Key<KEYS)
{
((Message->Code&IECODE_UP_PREFIX) ? KeyUp : KeyDown)(Key);
}
else if (Key==KEYS)
{
if (!(Message->Code&IECODE_UP_PREFIX))
{
OpenManual();
}
}
else
{
assert(Key==KEYS+1);
if (!(Message->Code&IECODE_UP_PREFIX))
{
if (CompileInfo==NULL)
{
CompileInfo=
CreateMessage(PROGRAM_NAME " " PROGRAM_VERSION " (" PROGRAM_DATE ")",
"Compiler: " COMPILER "\n"
"Date: %s, %s\n"
"CPU: " CPU "\n"
"AmigaOS: V%ld (Release " ROM_RELEASE ")",
CompileDate, CompileTime, ROM_VERSION);
}
}
}
break;
}
}
}
}
/************************************************************************/
/* */
/* Open the game font */
/* */
/************************************************************************/
static INLINE int ObtainFont(void)
{
if ((DiskfontBase=OpenLibrary((char *)DiskfontName,0))==NULL)
{
DisplayError(MSG_NO_LIBRARY,DiskfontName);
}
if (TextAttr.ta_Name!=NULL)
{
if ((data.font=(DiskfontBase!=NULL ? OpenDiskFont : OpenFont)(&TextAttr))==NULL)
{
DisplayError(MSG_FONT_ERROR,TextAttr.ta_Name,TextAttr.ta_YSize);
}
}
if (data.font==NULL)
{
static struct TextAttr TimesAttr={"Times.font", 18, 0, 0};
data.font=(DiskfontBase!=NULL ? OpenDiskFont : OpenFont)(&TimesAttr);
if (data.font==NULL)
{
DisplayError(MSG_FONT_ERROR,TimesAttr.ta_Name,TimesAttr.ta_YSize);
data.font=OpenFont(display.Screen->Screen->Font);
if (data.font==NULL)
{
static struct TextAttr TopazAttr={"topaz.font", 9, 0, 0};
data.font=OpenFont(&TopazAttr);
}
}
}
CloseLibrary(DiskfontBase);
return data.font!=NULL;
}
/************************************************************************/
/* */
/* Make an iconify gadget for our window */
/* */
/************************************************************************/
static INLINE void CreateIconifyGadget(void)
{
if (CreateIconifyImageClass()!=NULL)
{
if ((IconifyGadget.GadgetRender=NewObjectA(IconifyImageClass,NULL,NULL))!=NULL)
{
Object *DepthImage;
IconifyGadget.SelectRender=IconifyGadget.GadgetRender;
DepthImage=NewObject(NULL, SYSICLASS,
SYSIA_DrawInfo, display.DrawInfo,
SYSIA_Which, DEPTHIMAGE,
SYSIA_Size, ((display.Screen->Screen->Flags & SCREENHIRES) ?
((display.Screen->Screen->ViewPort.Modes & LACE) ?
SYSISIZE_HIRES : SYSISIZE_MEDRES) :
SYSISIZE_LOWRES),
TAG_DONE);
if (DepthImage!=NULL)
{
{
ULONG Width;
GetAttr(IA_Width,DepthImage,&Width);
IconifyGadget.Width=(WORD)Width;
}
DisposeObject(DepthImage);
IconifyGadget.LeftEdge=display.window->BorderRight-2*IconifyGadget.Width;
IconifyGadget.Height=display.window->BorderTop;
((struct Image *)IconifyGadget.GadgetRender)->Width=IconifyGadget.Width;
((struct Image *)IconifyGadget.GadgetRender)->Height=IconifyGadget.Height;
AddGadget(display.window,&IconifyGadget,0);
RefreshGadgets(display.window->FirstGadget,display.window,NULL);
}
}
}
}
/************************************************************************/
/* */
/* Allocate all GUI related resources (except for the menu) */
/* */
/************************************************************************/
static void OpenGUI(void)
{
if (display.Screen!=NULL || (display.Screen=GetScreen(ScreenDescription,NewBroker.nb_Name))!=NULL)
{
display.DrawInfo=GetScreenDrawInfo(display.Screen->Screen);
if ((display.VisualInfo=GetVisualInfo(display.Screen->Screen,NULL))!=NULL)
{
static struct TagItem LayoutTags[]=
{
{GTMN_NewLookMenus, TRUE},
{TAG_DONE}
};
LayoutMenusA(display.Menustrip,display.VisualInfo,LayoutTags);
if (ObtainFont())
{
WORD X, Y, Width, Height;
ULONG IntuiLock;
IntuiLock=LockIBase(0);
X=display.Screen->Screen->MouseX;
Y=display.Screen->Screen->MouseY;
UnlockIBase(IntuiLock);
display.OriginX=display.Screen->Screen->WBorLeft;
display.OriginY=display.Screen->Screen->WBorTop+display.Screen->Screen->Font->ta_YSize+1;
Width=WINDOW_WIDTH+display.OriginX+display.Screen->Screen->WBorRight;
Height=WINDOW_HEIGHT+display.OriginY+display.Screen->Screen->WBorBottom;
if (Width<=display.Screen->Screen->Width && Height<=display.Screen->Screen->Height)
{
static struct TagItem WindowTags[]=
{
{WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH | WFLG_ACTIVATE | WFLG_NEWLOOKMENUS},
{WA_RptQueue, 0},
{WA_PointerDelay, TRUE},
{TAG_DONE}
};
X-=Width/2;
Y-=Height/2;
display.window=OpenWindowTags(NULL,
WA_Left, X,
WA_Top, Y,
WA_Width, Width,
WA_Height, Height,
WA_ScreenTitle, GetString(MSG_SCREEN_TITLE),
WA_PubScreen, display.Screen->Screen,
WA_Title, WindowTitle,
TAG_MORE, WindowTags);
if (display.window!=NULL)
{
display.window->UserData=((struct Process *)WindowPort.mp_SigTask)->pr_WindowPtr;
((struct Process *)WindowPort.mp_SigTask)->pr_WindowPtr=display.window;
CreateIconifyGadget();
if (AllocateBitmaps())
{
if (LoadSprites())
{
SetMenuStrip(display.window,display.Menustrip);
display.window->UserPort=&WindowPort;
ModifyIDCMP(display.window,
IDCMP_MENUPICK |
IDCMP_GADGETUP |
IDCMP_CLOSEWINDOW |
IDCMP_REFRESHWINDOW |
IDCMP_RAWKEY |
IDCMP_ACTIVEWINDOW |
IDCMP_INACTIVEWINDOW);
if (display.window->Flags & WFLG_WINDOWACTIVE)
{
AllocateJoystickCounter=JOYSTICK_TRIES;
}
if (scoring.UserName[0]=='\0')
{
OpenChangeUserWindow();
}
return;
}
}
else
{
DisplayError(0,ERROR_NO_FREE_STORE);
}
}
else
{
DisplayError(MSG_WINDOW_ERROR);
}
}
else
{
DisplayError(MSG_SCREENSIZE_ERROR,ScreenDescription,Width,Height);
}
}
}
else
{
DisplayError(0,ERROR_NO_FREE_STORE);
}
}
else
{
LONG Error;
Error=IoErr();
if (Error==OSERR_PUBNOTUNIQUE)
{
char *String;
String=GS_FormatString(GetString(MSG_OSERR_PUBNOTUNIQUE),&NewBroker.nb_Name,NULL,NULL);
DisplayError(MSG_SCREEN_ERROR,ScreenDescription,String);
GS_MemoryFree(String);
}
else
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_SCREEN_ERROR,ScreenDescription,ErrorString(String,Error));
}
}
CloseGUI();
}
/************************************************************************/
/* */
/* Handle config/control/joystick menu change */
/* */
/************************************************************************/
static INLINE void ChangeJoystick(const struct MenuItem *Item)
{
if (Item->Flags & CHECKED)
{
if (!MiscState.Joystick)
{
AllocateJoystickCounter=JOYSTICK_TRIES;
}
}
else
{
FreeJoystick();
}
}
/************************************************************************/
/* */
/* Handle config/display/msit menu change */
/* */
/************************************************************************/
static INLINE int ChangeGender(const struct MenuItem *Item)
{
if (data.gender!=!!(Item->Flags & CHECKED))
{
FreeSprites();
if (LoadSprites())
{
return TRUE;
}
CloseGUI();
}
return FALSE;
}
/************************************************************************/
/* */
/* Handle config/display/dynamic menu change */
/* */
/************************************************************************/
static INLINE int ChangeDynamic(const struct MenuItem *Item)
{
if (Item->Flags & CHECKED)
{
if (!display.dynamic)
{
ObtainDynamic();
return (int)display.dynamic;
}
}
else if (display.dynamic)
{
ReleaseDynamic();
return TRUE;
}
return FALSE;
}
/************************************************************************/
/* */
/* Set the window title */
/* */
/************************************************************************/
void UpdateWindowTitle(void)
{
struct
{
const char *User;
const char *Garden;
} Params;
GS_MemoryFree(WindowTitle);
if (scoring.UserName[0]!='\0')
{
Params.User=scoring.UserName;
}
else
{
Params.User=GetString(MSG_USER_UNKNOWN);
}
if (board.Name==NULL)
{
WindowTitle=GS_FormatString("%s",&Params.User,NULL,Locale);
}
else
{
Params.Garden=board.Name;
WindowTitle=GS_FormatString("%s: %s",&Params,NULL,Locale);
}
if (display.window!=NULL)
{
SetWindowTitles(display.window,WindowTitle,(UBYTE *)~0);
}
scoring.mine.score=0;
}
/************************************************************************/
/* */
/* */
/************************************************************************/
static void HandleMessageWindow(struct Window **WindowPtr)
{
struct Window *Window;
Window=*WindowPtr;
if (Window!=NULL)
{
if (SysReqHandler(Window,NULL,FALSE)!=-2)
{
FreeSysRequest(Window);
*WindowPtr=NULL;
}
}
}
/************************************************************************/
static void EnableMenu(UWORD ID, int Item)
{
struct Menu *Menu;
Menu=(struct Menu *)FindMenu(ID);
if (display.window!=NULL)
{
OnMenu(display.window,((ULONG)(Item ? GTMENUITEM_USERDATA(Menu) : GTMENU_USERDATA(Menu)))>>16);
}
else
{
Menu->Flags|=Item ? ITEMENABLED : MENUENABLED;
}
}
/************************************************************************/
/* */
/* Load selected boards. */
/* Returns TRUE if boards have changed. */
/* */
/************************************************************************/
static int LoadBoards(void)
{
static struct MenuItem *BoardItem;
struct MenuItem *Item;
struct StringNode *Name;
for (Item=((struct Menu *)FindMenu(MSG_GARDENS_MENU))->FirstItem, Name=GardenStrings;
Item!=NULL && !(Item->Flags&CHECKED);
Item=Item->NextItem, Name=Name->Next)
{
assert(Name!=NULL);
}
if (Item!=NULL && BoardItem!=Item)
{
LONG *File;
BPTR OldCurrentDir;
OldCurrentDir=CurrentDir(GardenDir);
if ((File=ReadFile(((char *)(Name+1))+1))!=NULL)
{
LONG Size;
Size=(*File)-12;
if (Size>0 && ((Size%sizeof(BOARD))==0) && strncmp((char *)(File+1),"mris Garden!",12)==0)
{
LONG i;
for (i=0; i<Size/sizeof(BOARD); i++)
{
if (check_board(((BOARD *)(((char *)(File+1))+12))+i))
{
DisplayError(MSG_LOADGARDEN_ERROR,((char *)(Name+1))+1,GetString(MSG_INVALIDGARDEN_ERROR));
Size=0;
}
}
if (Size>0)
{
if (board.list!=NULL)
{
FreeFile((LONG *)(((char *)board.list)-12)-1);
}
board.Name=((char *)(Name+1))+1;
board.boards=Size/sizeof(BOARD);
board.list=(BOARD *)(((char *)(File+1))+12);
BoardItem=Item;
CurrentDir(OldCurrentDir);
GS_ReleaseScoreHandle(scoring.ScoreHandle);
scoring.ScoreHandle=NULL;
UpdateWindowTitle();
EnableMenu(MSG_DEMO_BOARD_MENU,TRUE);
EnableMenu(MSG_DEMO_SCORES_MENU,TRUE);
return TRUE;
}
}
else
{
DisplayError(MSG_LOADGARDEN_ERROR,((char *)(Name+1))+1,GetString(MSG_NOGARDEN_ERROR));
}
FreeFile(File);
}
else
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_LOADGARDEN_ERROR,((char *)(Name+1))+1,ErrorString(String,IoErr()));
}
CurrentDir(OldCurrentDir);
if (display.window!=NULL)
{
ClearMenuStrip(display.window);
BoardItem->Flags|=CHECKED;
Item->Flags&=~CHECKED;
ResetMenuStrip(display.window,display.Menustrip);
}
}
return FALSE;
}
/************************************************************************/
static struct DiskObject *GetPutDiskObject(struct DiskObject *DiskObject, char *Name)
{
if (DiskObject==NULL)
{
if ((DiskObject=GetDiskObject(Name))==NULL)
{
LONG Error;
Error=IoErr();
if (Error==ERROR_OBJECT_NOT_FOUND)
{
DiskObject=&mrisIcon;
}
else
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_GETICON_ERROR,Name,ErrorString(String,Error));
}
}
}
else
{
if (!PutDiskObject(Name,DiskObject))
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_PUTICON_ERROR,Name,ErrorString(String,IoErr()));
DiskObject=NULL;
}
}
return DiskObject;
}
/************************************************************************/
/* */
/* Get or Put the default icon */
/* If DiskObject==NULL, then get the default icon. */
/* If DiskObject!=NULL, then write it as default icon. */
/* */
/************************************************************************/
static struct DiskObject *DoDefaultIcon(struct DiskObject *DiskObject)
{
BPTR OldCurrentDir;
if (WorkbenchMessage!=NULL)
{
assert(WorkbenchMessage->sm_NumArgs>0 && WorkbenchMessage->sm_ArgList[0].wa_Name!=NULL);
OldCurrentDir=CurrentDir(WorkbenchMessage->sm_ArgList[0].wa_Lock);
DiskObject=GetPutDiskObject(DiskObject,WorkbenchMessage->sm_ArgList[0].wa_Name);
}
else
{
char ProgramName[256];
GetProgramName(ProgramName,sizeof(ProgramName));
OldCurrentDir=CurrentDir(GetProgramDir());
DiskObject=GetPutDiskObject(DiskObject,FilePart(ProgramName));
}
CurrentDir(OldCurrentDir);
return DiskObject;
}
/************************************************************************/
static INLINE void ReconstructGame(void)
{
if (display.window!=NULL)
{
KeyDown(KEY_PAUSE);
KeyUp(KEY_PAUSE);
if (MiscState.GameMode)
{
RedrawGame();
}
}
}
/************************************************************************/
/* */
/* Compare tooltype */
/* */
/************************************************************************/
static int CompareTooltype(const char *ToolType, const char *Name)
{
int Parenthesis;
while (*ToolType==' ')
{
ToolType++;
}
if ((Parenthesis=(*ToolType=='(')))
{
while (*(++ToolType)==' ')
;
}
while (*Name!='\0')
{
if (toupper(*ToolType)!=toupper(*Name))
{
return FALSE;
}
Name++;
ToolType++;
}
return (*ToolType=='\0' || *ToolType==' ' || *ToolType=='=' || (Parenthesis && *ToolType==')'));
}
/************************************************************************/
/* */
/* Free the new tooltype array */
/* */
/************************************************************************/
static void FreeTooltypes(char **ToolTypes)
{
char **ToolType;
for (ToolType=ToolTypes; *ToolType; ToolType++)
{
int i;
for (i=0; i<ARRAYSIZE(MrisToolTypes); i++)
{
if (CompareTooltype(*ToolType,MrisToolTypes[i]))
{
GS_MemoryFree(*ToolType);
}
}
}
GS_MemoryFree(ToolTypes);
}
/************************************************************************/
/* */
/* Create new tooltype array */
/* */
/************************************************************************/
static char **CreateTooltypes(char **ToolTypes)
{
ULONG Count;
char **ToolType;
char **NewToolTypes;
Count=0;
if (ToolTypes!=NULL)
{
for (ToolType=ToolTypes; *ToolType!=NULL; ToolType++)
{
int i;
Count++;
for (i=0; i<ARRAYSIZE(MrisToolTypes); i++)
{
if (CompareTooltype(*ToolType,MrisToolTypes[i]))
{
Count--;
break;
}
}
}
}
if ((NewToolTypes=GS_MemoryAlloc(sizeof(char *)*(Count+ARRAYSIZE(MrisToolTypes)+1)))!=NULL)
{
char **NewToolType;
int Error;
int i;
NewToolType=NewToolTypes;
Error=FALSE;
for (i=0; !Error && i<ARRAYSIZE(MrisToolTypes); i++)
{
char *Params[2];
Params[0]=MrisToolTypes[i];
switch (i)
{
case 8:
Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags & CHECKED) ? "YES" : "NO";
*NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
break;
case 9:
Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags & CHECKED) ? "YES" : "NO";
*NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
break;
case 10:
if (scoring.UserName[0]=='\0')
{
Params[1]="<user name>";
*NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
}
else
{
Params[1]=scoring.UserName;
*NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
}
break;
case 11:
Params[1]="<public screen name>";
*NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
break;
case 12:
if (ScreenDescription==NULL)
{
Params[1]="";
}
else
{
Params[1]=ScreenDescription;
}
*NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
break;
case 13:
Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags & CHECKED) ? "YES" : "NO";
*NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
break;
case 14:
if (TextAttr.ta_Name!=NULL)
{
*NewToolType=GS_FormatString("FONT=%s SIZE %u",&TextAttr,NULL,NULL);
}
else
{
Params[1]="<font description>";
*NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
}
break;
case 15:
Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags & CHECKED) ? "YES" : "NO";
*NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
break;
default:
assert(i<KEYS);
if (data.keysyms[i].Description!=GetString(MSG_KEY_UP+i))
{
Params[1]=data.keysyms[i].Description;
*NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
}
else
{
Params[1]="<key description>";
*NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
}
break;
}
if (*NewToolType==NULL)
{
Error=TRUE;
}
else
{
NewToolType++;
}
}
if (!Error)
{
if (ToolTypes!=NULL)
{
for (ToolType=ToolTypes; *ToolType!=NULL; ToolType++)
{
for (i=0; i<ARRAYSIZE(MrisToolTypes) && !CompareTooltype(*ToolType,MrisToolTypes[i]); i++)
;
if (i==ARRAYSIZE(MrisToolTypes))
{
*(NewToolType++)=*ToolType;
}
}
}
*NewToolType=NULL;
}
else
{
FreeTooltypes(NewToolTypes);
NewToolTypes=NULL;
}
}
return NewToolTypes;
}
/************************************************************************/
/* */
/* Save current config as default */
/* */
/************************************************************************/
static INLINE void SaveDefaultConfig(void)
{
struct DiskObject *DiskObject;
if ((DiskObject=DoDefaultIcon(NULL))!=NULL)
{
char **OldToolTypes;
OldToolTypes=DiskObject->do_ToolTypes;
if ((DiskObject->do_ToolTypes=CreateTooltypes(OldToolTypes))!=NULL)
{
UBYTE OldType;
char *OldDefaultTool;
struct DrawerData *OldDrawerData;
char *OldToolWindow;
OldType=DiskObject->do_Type;
OldDefaultTool=DiskObject->do_DefaultTool;
OldDrawerData=DiskObject->do_DrawerData;
OldToolWindow=DiskObject->do_ToolWindow;
DiskObject->do_Type=WBTOOL;
DiskObject->do_DefaultTool=NULL;
DiskObject->do_DrawerData=NULL;
DiskObject->do_ToolWindow=NULL;
DiskObject->do_StackSize=StackSize+2000;
DoDefaultIcon(DiskObject);
DiskObject->do_Type=OldType;
DiskObject->do_DefaultTool=OldDefaultTool;
DiskObject->do_DrawerData=OldDrawerData;
DiskObject->do_ToolWindow=OldToolWindow;
FreeTooltypes(DiskObject->do_ToolTypes);
}
DiskObject->do_ToolTypes=OldToolTypes;
if (DiskObject!=&mrisIcon)
{
FreeDiskObject(DiskObject);
}
}
}
/************************************************************************/
/* */
/* Put up the filerequester to save the configuration */
/* */
/************************************************************************/
static INLINE void OpenSaveConfig(void)
{
if (ConfigMessage.Requester==NULL)
{
if ((AslBase=OpenLibrary((char *)AslName,0))!=NULL)
{
static struct TagItem TagList[]=
{
{ASLFR_InitialPattern, (ULONG)"#?.info"},
{ASLFR_Flags1, FRF_DOSAVEMODE | FRF_DOPATTERNS},
{TAG_DONE}
};
ConfigMessage.Message.mn_ReplyPort=&MiscPort;
ConfigMessage.Requester=AllocAslRequestTags(ASL_FileRequest,
ASLFR_Screen, display.Screen->Screen,
ASLFR_Locale, Locale,
ASLFR_TitleText, GetString(MSG_SAVEREQUESTER_TITLE),
TAG_MORE, TagList);
if (ConfigMessage.Requester==NULL)
{
CloseLibrary(AslBase);
}
}
else
{
DisplayError(MSG_NO_LIBRARY,AslName);
}
}
if (ConfigMessage.Message.mn_Node.ln_Type==NT_UNKNOWN && ConfigMessage.Requester!=NULL)
{
if (WorkbenchMessage!=NULL && WorkbenchMessage->sm_NumArgs>0)
{
BPTR OldCurrentDir;
OldCurrentDir=CurrentDir(WorkbenchMessage->sm_ArgList[0].wa_Lock);
AsyncAslRequest(&ConfigMessage);
CurrentDir(OldCurrentDir);
}
else
{
AsyncAslRequest(&ConfigMessage);
}
}
}
/************************************************************************/
/* */
/* Check whether an icon is really our own program icon. */
/* "Name" must not have an ".info" suffix */
/* */
/************************************************************************/
static INLINE int CheckProgramIcon(BPTR DirLock, const char *Name)
{
if (WorkbenchMessage!=NULL)
{
if (SameLock(DirLock,WorkbenchMessage->sm_ArgList[0].wa_Lock)==LOCK_SAME)
{
if (stricmp(Name,WorkbenchMessage->sm_ArgList[0].wa_Name)==0)
{
return TRUE;
}
}
}
else
{
if (SameLock(DirLock,GetProgramDir())==LOCK_SAME)
{
char ProgramName[256];
GetProgramName(ProgramName,sizeof(ProgramName));
if (stricmp(Name,FilePart(ProgramName))==0)
{
return TRUE;
}
}
}
return FALSE;
}
/************************************************************************/
/* */
/* Do the save configuration */
/* */
/************************************************************************/
static INLINE void SaveConfig(void)
{
if (ConfigMessage.Result)
{
BPTR DirLock;
if ((DirLock=Lock(((struct FileRequester *)ConfigMessage.Requester)->fr_Drawer,SHARED_LOCK))!=MKBADDR(NULL))
{
char *Name;
LONG NameLength;
Name=((struct FileRequester *)ConfigMessage.Requester)->fr_File;
NameLength=strlen(Name);
if (NameLength>5 && stricmp(&Name[NameLength-5],".info")==0)
{
Name[NameLength-5]='\0';
NameLength=-NameLength;
}
if (!CheckProgramIcon(DirLock,Name))
{
struct DiskObject *DiskObject;
DirLock=CurrentDir(DirLock);
if ((DiskObject=GetDiskObject(Name))==NULL)
{
if (IoErr()==ERROR_OBJECT_NOT_FOUND)
{
DiskObject=DoDefaultIcon(NULL);
}
}
if (DiskObject!=NULL)
{
char **OldToolTypes;
OldToolTypes=DiskObject->do_ToolTypes;
if ((DiskObject->do_ToolTypes=CreateTooltypes(OldToolTypes))!=NULL)
{
char *MrisPath;
if ((MrisPath=GS_MemoryAlloc(1024))!=NULL)
{
if (NameFromLock(GetProgramDir(),MrisPath,1024))
{
if (WorkbenchMessage!=NULL)
{
assert(WorkbenchMessage->sm_NumArgs>0);
if (!AddPart(MrisPath,WorkbenchMessage->sm_ArgList[0].wa_Name,1024))
{
GS_MemoryFree(MrisPath);
MrisPath=NULL;
}
}
else
{
char ProgramName[256];
GetProgramName(ProgramName,sizeof(ProgramName));
if (!AddPart(MrisPath,FilePart(ProgramName),1024))
{
GS_MemoryFree(MrisPath);
MrisPath=NULL;
}
}
}
else
{
GS_MemoryFree(MrisPath);
MrisPath=NULL;
}
}
if (MrisPath!=NULL)
{
UBYTE OldType;
char *OldDefaultTool;
struct DrawerData *OldDrawerData;
char *OldToolWindow;
OldType=DiskObject->do_Type;
OldDefaultTool=DiskObject->do_DefaultTool;
OldDrawerData=DiskObject->do_DrawerData;
OldToolWindow=DiskObject->do_ToolWindow;
DiskObject->do_Type=WBPROJECT;
DiskObject->do_DefaultTool=MrisPath;
DiskObject->do_DrawerData=NULL;
DiskObject->do_ToolWindow=NULL;
DiskObject->do_StackSize=StackSize+2000;
if (!PutDiskObject(Name,DiskObject))
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_PUTICON_ERROR,Name,ErrorString(String,IoErr()));
}
DiskObject->do_Type=OldType;
DiskObject->do_DefaultTool=OldDefaultTool;
DiskObject->do_DrawerData=OldDrawerData;
DiskObject->do_ToolWindow=OldToolWindow;
GS_MemoryFree(MrisPath);
}
FreeTooltypes(DiskObject->do_ToolTypes);
}
DiskObject->do_ToolTypes=OldToolTypes;
if (DiskObject!=&mrisIcon)
{
FreeDiskObject(DiskObject);
}
}
DirLock=CurrentDir(DirLock);
}
else
{
SaveDefaultConfig();
}
if (NameLength<0)
{
Name[(-NameLength)-5]='.';
}
UnLock(DirLock);
}
}
FreeAslRequest(ConfigMessage.Requester);
ConfigMessage.Requester=NULL;
CloseLibrary(AslBase);
ConfigMessage.Message.mn_Node.ln_Type=NT_UNKNOWN;
}
/************************************************************************/
/* */
/* Process window messages */
/* */
/************************************************************************/
static int ProcessWindow(void)
{
struct IntuiMessage *Message;
if ((Message=(struct IntuiMessage *)GetMsg(&WindowPort))!=NULL)
{
if (Message->IDCMPWindow==display.window)
{
switch (Message->Class)
{
case IDCMP_GADGETUP:
if ((struct Gadget *)Message->IAddress==&IconifyGadget)
{
KeyDown(KEY_ICONIZE);
}
break;
case IDCMP_CLOSEWINDOW:
global.quit=TRUE;
break;
case IDCMP_REFRESHWINDOW:
BeginRefresh(display.window);
refresh_window();
EndRefresh(display.window,TRUE);
break;
case IDCMP_RAWKEY:
HandleKey(Message);
break;
case IDCMP_ACTIVEWINDOW:
if (((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags & CHECKED)
{
AllocateJoystickCounter=JOYSTICK_TRIES;
}
break;
case IDCMP_INACTIVEWINDOW:
InactiveWindow();
break;
case IDCMP_MENUPICK:
{
UWORD Selection;
int Modified;
Modified=FALSE;
Selection=Message->Code;
while (Selection!=MENUNULL && !global.quit && Sprites!=NULL)
{
struct MenuItem *Item;
UWORD UserData;
Item=ItemAddress(display.Menustrip,Selection);
UserData=((ULONG)GTMENUITEM_USERDATA(Item))&0xffff;
switch (UserData)
{
case MSG_GAME_ABOUT_MENU:
if (About==NULL)
{
About=CreateMessage(GetString(MSG_ABOUT_TITLE),
GetString(MSG_ABOUT_BODY),
PROGRAM_VERSION " (" PROGRAM_DATE ")",
GetString(MSG_BROKER_TITLE),
GetString(MSG_GAME_DESCRIPTION),
GetString(MSG_COPYRIGHT1),
GetString(MSG_COPYRIGHT2),
GetString(MSG_COPYRIGHT3),
data.gender ? PROGRAM_MSIT : PROGRAM_MRIS,
display.dynamic ? GetString(MSG_DISPLAYINFO_DYNAMIC) : "",
Sprites->Colors.DistinctColors,
Sprites->Colors.ColorCount);
}
break;
case MSG_CONFIG_DISPLAY_FONT_MENU:
OpenConfigFont();
break;
case MSG_CONFIG_DISPLAY_SCREEN_MENU:
OpenConfigScreen();
break;
case MSG_CONFIG_CONTROL_KEYS_MENU:
OpenConfigKeysWindow();
break;
case MSG_CONFIG_RANDOM_MENU:
if (!MiscState.GameMode)
{
data.random=(Item->Flags & CHECKED) ? TRUE : FALSE;
}
break;
case MSG_GAME_USER_MENU:
OpenChangeUserWindow();
break;
case MSG_GAME_ERRORS_MENU:
OpenErrorWindow();
break;
case MSG_GAME_QUIT_MENU:
global.quit=TRUE;
break;
case MSG_CONFIG_DISPLAY_DYNAMIC_MENU:
Modified|=ChangeDynamic(Item);
break;
case MSG_CONFIG_CONTROL_JOYSTICK_MENU:
ChangeJoystick(Item);
break;
case MSG_CONFIG_DISPLAY_MSIT_MENU:
Modified|=ChangeGender(Item);
break;
case MSG_GARDENS_MENU:
Modified|=LoadBoards();
break;
case MSG_CONFIG_SAVEDEFAULT_MENU:
SaveDefaultConfig();
break;
case MSG_CONFIG_SAVE_MENU:
OpenSaveConfig();
break;
default:
if (UserData>MSG_DEMO_MENU && UserData<=MSG_DEMO_SPRITES_MENU)
{
MiscState.JumpDemo=UserData-MSG_DEMO_MENU;
Modified=TRUE;
}
break;
}
Selection=Item->NextSelect;
}
if (!global.quit && Modified)
{
ReconstructGame();
}
}
break;
}
ReplyMsg(&Message->ExecMessage);
}
else if (Message->IDCMPWindow==ConfigKeysWindow)
{
ProcessConfigKeysWindow(Message);
}
else if (Message->IDCMPWindow==ChangeUserWindow)
{
ProcessChangeUserWindow(Message);
}
else
{
assert(Message->IDCMPWindow==ErrorWindow);
ProcessErrorWindow(Message);
}
return TRUE;
}
return FALSE;
}
/************************************************************************/
/* */
/* This is the main "game" loop while we're iconified */
/* */
/************************************************************************/
static INLINE void HandleIconified(void)
{
struct DiskObject *DiskObject;
struct AppIcon *AppIcon;
#ifdef DEBUG
DiskObject=NULL;
#endif
SetSignal(0,SIGBREAKF_CTRL_F);
if ((WorkbenchBase=OpenLibrary("workbench.library",37))!=NULL)
{
if ((DiskObject=DoDefaultIcon(NULL))==NULL)
{
DiskObject=&mrisIcon;
}
DiskObject->do_CurrentX=NO_ICON_POSITION;
DiskObject->do_CurrentY=NO_ICON_POSITION;
AppIcon=AddAppIconA(0,0,"mris",&WBPort,NULL,DiskObject,NULL);
}
while (!global.quit && display.window==NULL)
{
ULONG Signals;
Signals=Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | (1<<MiscPort.mp_SigBit));
if (Signals & SIGBREAKF_CTRL_C)
{
global.quit=TRUE;
}
else if (Signals & SIGBREAKF_CTRL_F)
{
OpenGUI();
ReconstructGame();
}
while (ProcessMisc())
;
while (ProcessWindow())
;
}
if (WorkbenchBase!=NULL)
{
if (AppIcon!=NULL)
{
struct Message *Message;
RemoveAppIcon(AppIcon);
while ((Message=GetMsg(&WBPort))!=NULL)
{
ReplyMsg(Message);
}
}
if (DiskObject!=&mrisIcon) /* DiskObject _is_ initialized */
{
FreeDiskObject(DiskObject);
}
CloseLibrary(WorkbenchBase);
}
}
/************************************************************************/
/* */
/* Process a message from MiscPort */
/* */
/************************************************************************/
static int ProcessMisc(void)
{
struct Message *Message;
if ((Message=GetMsg(&MiscPort))!=NULL)
{
if (Message==&GameSupportBase->Joystick.Request.io_Message)
{
HandleJoystick();
}
else if (Message==&FontMessage.Message)
{
if (ProcessConfigFont())
{
ReconstructGame();
}
}
else if (Message==&ConfigMessage.Message)
{
SaveConfig();
}
else if (Message==&ScreenMessage.Message)
{
if (ProcessConfigScreen())
{
ErrorFlag=FALSE;
CloseGUI();
if (display.Screen!=NULL)
{
FreeScreen(display.Screen,TRUE);
display.Screen=NULL;
}
OpenGUI();
ReconstructGame();
}
}
else /* CxMessage */
{
if (CxMsgType((CxMsg *)Message)==CXM_COMMAND)
{
switch (CxMsgID((CxMsg *)Message))
{
case CXCMD_APPEAR:
if (display.window==NULL)
{
SetSignal(SIGBREAKF_CTRL_F,SIGBREAKF_CTRL_F);
}
else
{
ShowWindow(display.window);
}
break;
case CXCMD_DISAPPEAR:
if (display.window!=NULL)
{
KeyDown(KEY_ICONIZE);
}
break;
case CXCMD_KILL:
SetSignal(SIGBREAKF_CTRL_C,SIGBREAKF_CTRL_C);
break;
}
}
ReplyMsg(Message);
}
return TRUE;
}
return FALSE;
}
/************************************************************************/
/* */
/* This is the main game loop */
/* */
/************************************************************************/
static INLINE void Game(void)
{
PROTOANIMATE((*animate));
timer_open();
animate = animate_demo;
while(!global.quit)
{
if (display.window!=NULL)
{
int DoMessages;
HandleMessageWindow(&CompileInfo);
HandleMessageWindow(&About);
color_cycle();
if (CheckSignal(SIGBREAKF_CTRL_C))
{
global.quit=TRUE;
}
DoMessages=TRUE;
while (!global.quit && display.window!=NULL && DoMessages)
{
DoMessages=ProcessMisc();
/* process IDCMP message */
if (ProcessWindow())
{
DoMessages=TRUE;
}
/* process Manual message */
if (ProcessManual())
{
DoMessages=TRUE;
}
}
if (display.window!=NULL && !global.quit)
{
if (AllocateJoystickCounter>0)
{
if (GS_AllocateJoystick(&MiscPort,GPCT_ABSJOYSTICK))
{
AllocateJoystickCounter=0;
MiscState.Joystick=TRUE;
GS_SendJoystick();
}
else
{
AllocateJoystickCounter--;
}
}
if (MiscState.GameMode && !MiscState.GamePause && !MiscState.HappyBlanker)
{
if (GS_HappyBlanker())
{
MiscState.HappyBlanker=TRUE;
}
}
if(global.pressed & (1 << KEY_THROW))
{
if(global.throw == 0)
global.throw = 1;
}
else if(global.throw == 2)
global.throw = 0;
if(global.pressed & 1 << KEY_ICONIZE)
{
KeyDown(KEY_PAUSE);
InactiveWindow();
CloseGUI();
}
else
{
assert(animate != (PROTOANIMATE((*)))NULL);
animate = (PROTOANIMATE((*)))(*animate)((PROTOVOID(*))NULL);
show_updates();
timer_wait();
assert(monster.normals < 20);
}
}
}
else
{
HandleIconified();
}
}
if (MiscState.GameMode)
{
StopGame();
}
FreeJoystick();
timer_close();
}
/************************************************************************/
struct Menu *CreateMenustrip(struct NewMenu *NewMenu)
{
unsigned int i;
for (i=0; NewMenu[i].nm_Type!=NM_END; i++)
{
if ((ULONG)NewMenu[i].nm_Label<1024)
{
char *Item;
Item=GetString((LONG)NewMenu[i].nm_Label);
if (Item[0]!='\0')
{
NewMenu[i].nm_CommKey=Item;
}
NewMenu[i].nm_Label=Item+1;
}
}
return CreateMenusA(NewMenu,NULL);
}
/************************************************************************/
static INLINE void MyCreateMenustrip(void)
{
struct Menu *Menu;
UWORD MenuNum;
if ((display.Menustrip=CreateMenustrip(NewMenu))==NULL)
{
CloseAll(RETURN_ERROR,ERROR_NO_FREE_STORE);
}
for (Menu=display.Menustrip, MenuNum=0; Menu!=NULL; Menu=Menu->NextMenu, MenuNum++)
{
struct MenuItem *Item;
UWORD ItemNum;
GTMENU_USERDATA(Menu)=(APTR)(((ULONG)GTMENU_USERDATA(Menu))|(FULLMENUNUM(MenuNum,NOITEM,NOSUB)<<16));
for (Item=Menu->FirstItem, ItemNum=0; Item!=NULL; Item=Item->NextItem, ItemNum++)
{
GTMENUITEM_USERDATA(Item)=(APTR)(((ULONG)GTMENUITEM_USERDATA(Item))|(FULLMENUNUM(MenuNum,ItemNum,NOSUB)<<16));
}
}
}
/************************************************************************/
static INLINE void InitKeys(void)
{
int Key;
for (Key=0; Key<ARRAYSIZE(data.keysyms); Key++)
{
ChangeKey(Key,NULL);
}
}
/************************************************************************/
/* */
/* Locate a menu item */
/* */
/************************************************************************/
void *FindMenu(UWORD UserData)
{
struct Menu *Menu;
for (Menu=display.Menustrip; Menu!=NULL; Menu=Menu->NextMenu)
{
struct MenuItem *Item;
if ((((ULONG)GTMENU_USERDATA(Menu))&0xffff)==UserData)
{
return Menu;
}
for (Item=Menu->FirstItem; Item!=NULL; Item=Item->NextItem)
{
struct MenuItem *SubItem;
if ((((ULONG)GTMENUITEM_USERDATA(Item))&0xffff)==UserData)
{
return Item;
}
for (SubItem=Item->SubItem; SubItem!=NULL; SubItem=SubItem->NextItem)
{
if ((((ULONG)GTMENUITEM_USERDATA(SubItem))&0xffff)==UserData)
{
return SubItem;
}
}
}
}
return NULL;
}
/************************************************************************/
/* */
/* Determine default username */
/* */
/************************************************************************/
static INLINE void InitUser(void)
{
static const char * const UserVariables[]={"USER","USERNAME","REALNAME"};
int i;
for (i=ARRAYSIZE(UserVariables)-1;
i>=0 && GetVar(UserVariables[i],scoring.UserName,sizeof(scoring.UserName),0)<5;
i--)
;
if (i<0)
{
scoring.UserName[0]='\0';
}
}
/************************************************************************/
/* */
/* As usual, Commodore didn't properly design their localization */
/* facilities. Mris requires two strings which are country, not */
/* language dependent (time formats). Since we only have catalogs, */
/* I decided to put these strings into the catalog (although this is */
/* not correct). But then, CatComp complains about the % formatting */
/* commands... */
/* Therefore we use '\1' instead of %, and fix the strings in memory. */
/* */
/************************************************************************/
static char *RepairFormatString(LONG StringID)
{
char *String;
char *t;
String=GetString(StringID);
for (t=String; *t!='\0'; t++)
{
if (*t=='\1')
{
*t='%';
}
}
return String;
}
/************************************************************************/
static INLINE void Init(void)
{
BPTR OldCurrentDir;
MiscPort.mp_SigBit=WindowPort.mp_SigBit=AllocSignal(-1);
if ((GadToolsBase=OpenLibrary("gadtools.library",ROM_VERSION))==NULL)
{
MyExit(RETURN_CATASTROPHY,0);
}
if ((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",ROM_VERSION))==NULL ||
(IconBase=OpenLibrary("icon.library",ROM_VERSION))==NULL)
{
CloseAll(RETURN_FAIL,0);
}
OldCurrentDir=CurrentDir(GetProgramDir());
GameSupportBase=(struct GameSupportBase *)OpenLibrary("gamesupport.library",0);
CurrentDir(OldCurrentDir);
CloseLibrary(&DOSBase->dl_lib);
if (GameSupportBase==NULL)
{
CloseAll(RETURN_FAIL,0);
}
DOSBase=GameSupportBase->DOSBase;
IntuitionBase=GameSupportBase->IntuitionBase;
GfxBase=GameSupportBase->GfxBase;
UtilityBase=GameSupportBase->UtilityBase;
LayersBase=GameSupportBase->LayersBase;
KeymapBase=GameSupportBase->KeymapBase;
if ((CxBase=OpenLibrary("commodities.library",37))==NULL)
{
CloseAll(RETURN_FAIL,0);
}
if ((LocaleBase=GameSupportBase->LocaleBase)!=NULL)
{
static struct TagItem CatalogTags[]=
{
{OC_BuiltInLanguage, (ULONG)"deutsch"},
{OC_Version, 1},
{TAG_DONE}
};
Locale=OpenLocale(NULL);
if ((Catalog=OpenCatalogA(Locale,PROGRAM_NAME ".catalog",CatalogTags))==NULL)
{
LONG Error;
if ((Error=IoErr())!=0)
{
CloseAll(RETURN_FAIL,Error);
}
}
}
Formats.ElapsedTime=RepairFormatString(MSG_ELAPSED_TIME_FORMAT);
Formats.DateTime=RepairFormatString(MSG_DATE_FORMAT);
#if !defined(__SASC)
if ((DitherPattern=AllocMem(2*sizeof(UWORD),MEMF_CHIP))==NULL)
{
CloseAll(RETURN_FAIL,ERROR_NO_FREE_STORE);
}
DitherPattern[0]=0x5555;
DitherPattern[1]=0xaaaa;
#endif
scoring.mine.Score.Name=scoring.UserName;
scoring.display=-1;
WBPort.mp_SigTask=MiscPort.mp_SigTask=WindowPort.mp_SigTask=FindTask(NULL);
}
/************************************************************************/
void StartGame(void)
{
struct Menu *Menu;
struct MenuItem *Item;
Item=(struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU);
OffMenu(display.window,((ULONG)GTMENUITEM_USERDATA(Item))>>16);
data.random=(Item->Flags & CHECKED) ? TRUE : FALSE;
Menu=(struct Menu *)FindMenu(MSG_GARDENS_MENU);
OffMenu(display.window,((ULONG)GTMENU_USERDATA(Menu))>>16);
Menu=(struct Menu *)FindMenu(MSG_DEMO_MENU);
OffMenu(display.window,((ULONG)GTMENU_USERDATA(Menu))>>16);
MiscState.GameMode=TRUE;
MiscState.JumpDemo=0;
MiscState.GamePause=FALSE;
LoadBoards();
}
/************************************************************************/
void StopGame(void)
{
if (MiscState.HappyBlanker)
{
MiscState.HappyBlanker=FALSE;
GS_NoHappyBlanker();
}
history.msec += global.msec;
scoring.mine.score = global.score;
scoring.mine.screen = global.screen;
scoring.mine.elapsed = (unsigned)(history.msec / 1000);
if (scoring.ScoreHandle==NULL && board.boards>0)
{
scoring.ScoreHandle=GS_ObtainScoreHandle(&ScoreDef.ScoreDef,board.Name,scoring.UserName);
}
if (scoring.ScoreHandle!=NULL && scoring.mine.score>=SCORE_THRESHOLD)
{
GS_InsertScore(scoring.ScoreHandle,&scoring.mine.Score);
}
else
{
ULONG Micros;
CurrentTime(&scoring.mine.Score.TimeStamp,&Micros);
}
EnableMenu(MSG_DEMO_MENU,FALSE);
EnableMenu(MSG_GARDENS_MENU,FALSE);
EnableMenu(MSG_CONFIG_RANDOM_MENU,TRUE);
MiscState.GameMode=FALSE;
MiscState.GamePause=FALSE;
}
/************************************************************************/
/* */
/* Read garden directory, and create initial "Gardens" menu */
/* */
/************************************************************************/
static INLINE void InitGardens(void)
{
LONG Error;
if ((GardenDir=Lock("PROGDIR:mris gardens",SHARED_LOCK))!=MKBADDR(NULL))
{
struct ExAllControl *ExAllControl;
BPTR OldCurrentDir;
OldCurrentDir=CurrentDir(GardenDir);
if ((ExAllControl=AllocDosObject(DOS_EXALLCONTROL,NULL))!=NULL)
{
void *ExAllData;
if ((ExAllData=GS_MemoryAlloc(4096))!=NULL)
{
BOOL More;
Error=0;
ExAllControl->eac_LastKey=0;
ExAllControl->eac_MatchString=NULL;
ExAllControl->eac_MatchFunc=NULL;
do
{
More=ExAll(GardenDir,ExAllData,4096,ED_SIZE,ExAllControl);
if (!More)
{
LONG Err;
if ((Err=IoErr())!=ERROR_NO_MORE_ENTRIES)
{
if (Error==0)
{
Error=Err;
}
break;
}
}
if (ExAllControl->eac_Entries>0)
{
struct ExAllData *Data;
for (Data=ExAllData; Data!=NULL; Data=Data->ed_Next)
{
if ((Data->ed_Size>=12+sizeof(BOARD)) && ((Data->ed_Size-12)%sizeof(BOARD))==0)
{
BPTR Filehandle;
if ((Filehandle=Open(Data->ed_Name,MODE_OLDFILE))!=MKBADDR(NULL))
{
char Header[12];
if (Read(Filehandle,Header,12)==12)
{
if (strncmp(Header,"mris Garden!",12)==0)
{
struct StringNode *Name;
if ((Name=GS_MemoryAlloc(sizeof(struct StringNode)+strlen(Data->ed_Name)+1+1))!=NULL)
{
struct StringNode **Current;
strcpy(((char *)(Name+1))+1,Data->ed_Name);
for (Current=&GardenStrings;
*Current!=NULL && (Locale!=NULL ?
StrnCmp(Locale,Data->ed_Name,
((char *)((*Current)+1))+1,
-1,SC_COLLATE2) :
Stricmp(Data->ed_Name,
((char *)((*Current)+1))+1))>0;
Current=&(*Current)->Next)
;
Name->Next=*Current;
*Current=Name;
}
else
{
Error=ERROR_NO_FREE_STORE;
}
}
}
Close(Filehandle);
}
}
}
}
}
while (More);
if (Error==ERROR_NO_MORE_ENTRIES)
{
Error=0;
}
GS_MemoryFree(ExAllData);
if (Error==0)
{
struct StringNode *Name;
struct MenuItem **Item;
ULONG Count;
Count=0;
Item=&((struct Menu *)FindMenu(MSG_GARDENS_MENU))->FirstItem;
for (Name=GardenStrings; Error==0 && Name!=NULL; Name=Name->Next)
{
struct NewMenu NewMenu[2];
NewMenu[0].nm_Type=NM_ITEM;
if (Count<10)
{
NewMenu[0].nm_CommKey=(char *)(Name+1);
*(char *)(Name+1)=Count==9 ? '0' : '1'+Count;
}
else
{
NewMenu[0].nm_CommKey=NULL;
}
NewMenu[0].nm_Label=((char *)(Name+1))+1;
NewMenu[0].nm_Flags=(stricmp(NewMenu[0].nm_Label,"Digits")==0) ? CHECKIT|CHECKED : CHECKIT;
NewMenu[0].nm_MutualExclude=~(1<<Count++);
NewMenu[0].nm_UserData=(APTR)MSG_GARDENS_MENU;
NewMenu[1].nm_Type=NM_END;
if ((*Item=(struct MenuItem *)CreateMenusA(NewMenu,NULL))!=NULL)
{
Item=&(*Item)->NextItem;
}
else
{
Error=ERROR_NO_FREE_STORE;
}
}
}
}
else
{
Error=ERROR_NO_FREE_STORE;
}
FreeDosObject(DOS_EXALLCONTROL,ExAllControl);
}
else
{
Error=ERROR_NO_FREE_STORE;
}
CurrentDir(OldCurrentDir);
if (Error==0)
{
LoadBoards();
UpdateWindowTitle();
}
}
else
{
Error=IoErr();
}
if (Error!=0)
{
CloseAll(RETURN_FAIL,Error);
}
}
/************************************************************************/
/* */
/* Process a YES/NO tooltype. */
/* */
/************************************************************************/
static void ProcessBoolean(char **ToolTypes, char *Name, UWORD MenuID)
{
char *ToolType;
if ((ToolType=FindToolType(ToolTypes,Name))!=NULL)
{
struct MenuItem *Item;
Item=FindMenu(MenuID);
if (MatchToolValue(ToolType,"YES"))
{
Item->Flags|=CHECKED;
}
else if (MatchToolValue(ToolType,"NO"))
{
Item->Flags&=~CHECKED;
}
else
{
while (*ToolType==' ' || *ToolType=='\t')
{
ToolType++;
}
if (ToolType=='\0')
{
Item->Flags|=CHECKED;
}
else
{
DisplayError(MSG_BOOLTOOLTYPE_ERROR,ToolType,Name);
}
}
}
}
/************************************************************************/
/* */
/* Process a tooltype array. */
/* */
/************************************************************************/
static void ProcessToolTypes(char **ToolTypes)
{
char *ToolType;
int Key;
ProcessBoolean(ToolTypes,MrisToolTypes[8],MSG_CONFIG_RANDOM_MENU);
ProcessBoolean(ToolTypes,MrisToolTypes[9],MSG_CONFIG_DISPLAY_DYNAMIC_MENU);
ProcessBoolean(ToolTypes,MrisToolTypes[13],MSG_CONFIG_CONTROL_JOYSTICK_MENU);
ProcessBoolean(ToolTypes,MrisToolTypes[15],MSG_CONFIG_DISPLAY_MSIT_MENU);
for (Key=0; Key<KEYS; Key++)
{
if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[Key]))!=NULL)
{
ChangeKey(Key,ToolType);
}
}
if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[10]))!=NULL)
{
while (*ToolType==' ')
{
ToolType++;
}
strncpy(scoring.UserName,ToolType,sizeof(scoring.UserName)-1);
scoring.UserName[sizeof(scoring.UserName)-1]='\0';
}
if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[11]))!=NULL)
{
while (*ToolType==' ')
{
ToolType++;
}
GS_MemoryFree(ScreenDescription);
if (*ToolType=='\0')
{
ScreenDescription=NULL;
}
else
{
if ((ScreenDescription=GS_FormatString("PUBSCREEN \"%s\"",&ToolType,NULL,NULL))==NULL)
{
DisplayError(0,ERROR_NO_FREE_STORE);
}
}
}
if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[12]))!=NULL)
{
while (*ToolType==' ')
{
ToolType++;
}
GS_MemoryFree(ScreenDescription);
if ((ScreenDescription=GS_MemoryAlloc(strlen(ToolType)+1))!=NULL)
{
strcpy(ScreenDescription,ToolType);
}
else
{
DisplayError(0,ERROR_NO_FREE_STORE);
}
}
if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[14]))!=NULL)
{
LONG Error;
struct TextAttr NewTextAttr;
if ((Error=MakeTextAttr(ToolType,&NewTextAttr))==0)
{
if (NewTextAttr.ta_YSize<CELL_HEIGHT)
{
FreeVec(TextAttr.ta_Name);
TextAttr.ta_Name=NewTextAttr.ta_Name;
TextAttr.ta_YSize=NewTextAttr.ta_YSize;
}
else
{
FreeVec(NewTextAttr.ta_Name);
}
}
else
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_FONTDESC_ERROR,ToolType,ErrorString(String,IoErr()));
}
}
}
/************************************************************************/
/* */
/* Check out our program name */
/* */
/************************************************************************/
static INLINE void CheckName(void)
{
const char *Name;
char ProgramName[256];
if (WorkbenchMessage==NULL)
{
GetProgramName(ProgramName,sizeof(ProgramName));
Name=FilePart(ProgramName);
}
else
{
Name=FindTask(NULL)->tc_Node.ln_Name;
}
while (*Name!='\0')
{
if (strnicmp(Name,"msit",4)==0)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags|=CHECKED;
break;
}
Name++;
}
}
/************************************************************************/
/* */
/* Get arguments */
/* */
/************************************************************************/
static INLINE void ObtainArgs(void)
{
CheckName();
if (WorkbenchMessage==NULL)
{
struct DiskObject *DiskObject;
if ((DiskObject=DoDefaultIcon(NULL))!=NULL)
{
struct
{
LONG Random;
LONG NoRandom;
LONG Dynamic;
LONG NoDynamic;
LONG Joystick;
LONG NoJoystick;
LONG mris;
LONG msit;
char *User;
char *Pubscreen;
char *Screen;
char *Font;
char *Keys[KEYS];
} Arguments;
struct RDArgs *RDArgs;
ProcessToolTypes(DiskObject->do_ToolTypes);
memset(&Arguments,0,sizeof(Arguments));
if ((RDArgs=ReadArgs("RANDOM/S,NORANDOM/S,"
"DYNAMIC/S,NODYNAMIC/S,"
"JOYSTICK/S,NOJOYSTICK/S,"
"MRIS/S,MSIT/S,"
"USER=USERNAME/K,"
"PUBSCREEN/K,"
"SCREEN/K,"
"FONT/K,"
"UP/K,DOWN/K,LEFT/K,RIGHT/K,THROW/K,PAUSE/K,QUIT/K,ICONIZE/K",
(LONG *)&Arguments,NULL))!=NULL)
{
int Key;
if (Arguments.Random)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags|=CHECKED;
}
if (Arguments.NoRandom)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags&=~CHECKED;
}
if (Arguments.Dynamic)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags|=CHECKED;
}
if (Arguments.NoDynamic)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags&=~CHECKED;
}
if (Arguments.Joystick)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags|=CHECKED;
}
if (Arguments.NoJoystick)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags&=~CHECKED;
}
if (Arguments.mris)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags&=~CHECKED;
}
if (Arguments.msit)
{
((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags|=CHECKED;
}
if (Arguments.User!=NULL)
{
strncpy(scoring.UserName,Arguments.User,sizeof(scoring.UserName)-1);
scoring.UserName[sizeof(scoring.UserName)-1]='\0';
}
for (Key=0; Key<KEYS; Key++)
{
if (Arguments.Keys[Key]!=NULL)
{
if (Arguments.Keys[Key][0]=='\0')
{
ChangeKey(Key,NULL);
}
else
{
ChangeKey(Key,Arguments.Keys[Key]);
}
}
}
if (Arguments.Pubscreen!=NULL)
{
GS_MemoryFree(ScreenDescription);
if (Arguments.Pubscreen[0]=='\0')
{
ScreenDescription=NULL;
}
else
{
if ((ScreenDescription=GS_FormatString("PUBSCREEN \"%s\"",&Arguments.Pubscreen,NULL,NULL))==NULL)
{
DisplayError(0,ERROR_NO_FREE_STORE);
}
}
}
if (Arguments.Screen!=NULL)
{
GS_MemoryFree(ScreenDescription);
if ((ScreenDescription=GS_MemoryAlloc(strlen(Arguments.Screen)+1))!=NULL)
{
strcpy(ScreenDescription,Arguments.Screen);
}
else
{
DisplayError(0,ERROR_NO_FREE_STORE);
}
}
if (Arguments.Font!=NULL)
{
struct TextAttr NewTextAttr;
LONG Error;
if ((Error=MakeTextAttr(Arguments.Font,&NewTextAttr))==0)
{
if (NewTextAttr.ta_YSize<CELL_HEIGHT)
{
FreeVec(TextAttr.ta_Name);
TextAttr.ta_Name=NewTextAttr.ta_Name;
TextAttr.ta_YSize=NewTextAttr.ta_YSize;
}
else
{
FreeVec(NewTextAttr.ta_Name);
}
}
else
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_FONTDESC_ERROR,Arguments.Font,ErrorString(String,Error));
}
}
FreeArgs(RDArgs);
}
else
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_COMMANDLINE_ERROR,ErrorString(String,IoErr()));
}
if (DiskObject!=&mrisIcon)
{
FreeDiskObject(DiskObject);
}
}
}
else
{
LONG Count;
for (Count=0; Count<WorkbenchMessage->sm_NumArgs; Count++)
{
BPTR OldCurrentDir;
char *Name;
struct DiskObject *DiskObject;
OldCurrentDir=CurrentDir(WorkbenchMessage->sm_ArgList[Count].wa_Lock);
Name=WorkbenchMessage->sm_ArgList[Count].wa_Name;
if ((DiskObject=GetDiskObject(Name))!=NULL)
{
ProcessToolTypes(DiskObject->do_ToolTypes);
FreeDiskObject(DiskObject);
}
else
{
char String[ERRORSTRING_LENGTH];
DisplayError(MSG_GETICON_ERROR,Name,ErrorString(String,IoErr()));
}
CurrentDir(OldCurrentDir);
}
}
data.random=(((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags & CHECKED) ? TRUE : FALSE;
}
/************************************************************************/
static INLINE void CreateBroker(void)
{
LONG Error;
ULONG Count;
Count=0;
NewBroker.nb_Title=GetString(MSG_BROKER_TITLE);
NewBroker.nb_Descr=GetString(MSG_GAME_DESCRIPTION);
do
{
GS_MemoryFree(NewBroker.nb_Name);
if (Count==0)
{
NewBroker.nb_Name=GS_FormatString("mris",&Count,NULL,NULL);
}
else
{
NewBroker.nb_Name=GS_FormatString("mris.%lu",&Count,NULL,NULL);
}
if (NewBroker.nb_Name!=NULL)
{
if ((Broker=CxBroker(&NewBroker,&Error))==NULL)
{
Count++;
}
}
else
{
Error=ERROR_NO_FREE_STORE;
}
}
while (Error==CBERR_DUP);
ActivateCxObj(Broker,TRUE);
}
/************************************************************************/
void AmigaMain(void)
{
Init();
MyCreateMenustrip();
InitKeys();
InitUser();
ObtainArgs();
InitGardens();
CreateBroker();
OpenGUI();
Game();
CloseAll(RETURN_OK,0);
}